/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utils;

import java.util.ArrayList;

import model.Node;
import model.Term;
import repco.RepCo;

/**
 *
 * @author falxa
 */


public class Weightor 
{
    private final RepCo rc;
    
    private int termQuantity;
    private int minExponent;
            
    public Weightor(RepCo rc)
    {
        this.rc = rc;
        this.computeTermQty();
        this.minExponent = Integer.MAX_VALUE;
    }
    
    public int getExponent(double d)
    {
    	// TODO or NOT TODO recuperer l'exposant en base 10 du double
    	return -7;
    }
    
    public void computeTermQty()
    {
        int qty = 0;
        for (int i=0; i<this.rc.getTerms().size(); i++)
            qty += this.rc.getTerms().get(i).getQuantity();
        
        this.termQuantity = qty;
    }
    
    public double computeGlobalTermFrequency(int id)
    {
        double w = 0;
        
        int tqty = this.rc.getTerms().get(id).getQuantity();
        w = (double) tqty / (double) this.termQuantity;
        
        return w;
    }
    
    public double computeNodeTermFrequency(int node, int id)
    {
    	double w = 0;
    	
    	int tqty = this.rc.getNodes().get(node).countTerm(id);
    	int nodeqty = this.rc.getNodes().get(node).getTerms().size();
    			
    	w = (double) tqty / (double) nodeqty;
    	
    	return w;
    }
    
    public double computeTermIEF(int node, int term)
    {
    	double w = 0;
        
        //int totalTerm = this.rc.getNodes().get(node).getTerms().size();
        //int nbTerm = this.rc.getNodes().get(node).countTerm(term);
        
    	int totalNode = this.rc.getNodes().get(node).getTerms().size();
        int termNode = this.rc.getTerms().get(term).getPositions().get(node).size();
    	
        w = Math.log( (double) totalNode / (double) termNode);
        
        return w;
    }
    
    public int containingDocs(int term)
    {
    	Term t = this.rc.getTerms().get(term);
    	
        ArrayList<Integer> nodes = new ArrayList<>(t.getPositions().keySet());
        ArrayList<Integer> docs = new ArrayList<>();
        
        for (int i=0; i<nodes.size(); i++)
            if (!docs.contains(rc.getNodes().get(nodes.get(i)).getFdoc()))
                docs.add(rc.getNodes().get(nodes.get(i)).getFdoc());
        
        return docs.size();
    }
    
    public double computeTermIDF(int id)
    {
    	double w = 0;
        
        int nbDoc = this.rc.getDocuments().size();
        int containingDocs = this.containingDocs(id);
        
        w = (double) Math.log( (double) nbDoc/ (double) containingDocs);
        
        return w;
    }
    
    public double computeNodeWeight(int node)
    {
        double w = 1.;
        Node n = this.rc.getNodes().get(node);
        
        int size = n.getTerms().size();
        if (size == 0) size = 1;
        
        int typew = typeWeight(n.getType());
        
        for (Term t: n.getTerms())
        	w += t.getWeight().get(node);
        
        //if (size > 0) w *= (double) size; 
        w *= (double) typew;
        
        // TODO adapter le poids pour qu'il n'ait pas une consequence aussi drastique sur le poids des termes eux memes
        
        return w;
    }
    
    private int typeWeight(String t)
	{
    	int w;
    	
		if (t.equals("TITRE"))
			w = 4;
		else if (t.equals("SOUS-TITRE"))
			w = 3;
		else if (t.equals("P"))
			w = 2;
		else if (t.equals("ITEM"))
			w = 1;
		else
			w = 0;
    	
    	return w;
	}

	public void computeNodesWeight()
    {
    	for (Node n : this.rc.getNodes())
    		n.setWeight(computeNodeWeight(n.getID()));
    }
    
    public void computeTermsWeight()
    {
        double tf, idf, ief;
        Double nw;
        
        for (Term t: rc.getTerms())
        {
            idf = computeTermIDF(t.getID());
            
            for (Integer node: t.getWeight().keySet())
        	{
            	tf = computeNodeTermFrequency(node, t.getID());
            	ief = computeTermIEF(node, t.getID());
            	nw = tf * idf * ief;
            	
            	this.minExponent = Math.min(this.minExponent, getExponent(nw));
            	t.getWeight().put(node, nw);
        	}
        }
    }
    
    public void updateWeights()
    {
    	double pow =  Math.pow(10., this.minExponent);
    	
    	for (Term t: rc.getTerms())
        {
    		for (Integer node: t.getWeight().keySet())
        	{
    			double nw = t.getWeight().get(node);
    			nw *= 1./pow;
    			t.getWeight().put(node, nw);
        	}
        }
    }
    
    public void computeWeights()
    {
    	computeTermsWeight();
    	updateWeights();
    	computeNodesWeight();
    }
}
